package com.pur.zsms.common.dao;

import java.util.List;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceException;
import javax.persistence.Query;

import com.pur.zsms.common.support.JpaLockMode;
import com.pur.zsms.common.support.PageController;

/**
 * <p>帮助类，用于简化JPA数据访问。该类实现了JpaOperation接口中的方法。</p>
 * <p>Copyright: Copyright (c) 2008</p>
 * <p>Create Time: 2008-10-27</p>
 * @author wangzg002
 *
 */
public class JpaTemplate implements JpaOperations {
	/**
	 * JPA EntityManager
	 */
	private EntityManager em;

	/**通过传入JPA EntityManager 构造模板实例
	 * @param em JPA EntityManager
	 */
	public JpaTemplate(EntityManager em) {
		this.em = em;
	}

	/* (non-Javadoc)
	 * @see com.ulic.ucia.orm.jpa.JpaOperations#find(java.lang.Class, java.lang.Object)
	 */
	public <T> T find(Class<T> entityClass, Object id)
			throws PersistenceException {

		return em.find(entityClass, id);

	}

	/* (non-Javadoc)
	 * @see com.ulic.ucia.orm.jpa.JpaOperations#getReference(java.lang.Class, java.lang.Object)
	 */
	public <T> T getReference(Class<T> entityClass, Object id)
			throws PersistenceException {
		return em.getReference(entityClass, id);
	}

	/* (non-Javadoc)
	 * @see com.ulic.ucia.orm.jpa.JpaOperations#contains(java.lang.Object)
	 */
	public boolean contains(Object entity) throws PersistenceException {
		return new Boolean(em.contains(entity)).booleanValue();
	}

	/* (non-Javadoc)
	 * @see com.ulic.ucia.orm.jpa.JpaOperations#find(java.lang.String)
	 */
	@SuppressWarnings("unchecked")
	public List find(final String queryString,
			final PageController pageController) throws PersistenceException {
		return find(queryString, pageController, (Object[]) null);
	}

	/* (non-Javadoc)
	 * @see com.ulic.ucia.orm.jpa.JpaOperations#find(java.lang.String, java.lang.Object[])
	 */
	@SuppressWarnings("unchecked")
	public List find(final String queryString,
			final PageController pageController, final Object... values)
			throws PersistenceException {
		Query queryObject = em.createQuery(queryString);
		if (values != null) {
			for (int i = 0; i < values.length; i++) {

				queryObject.setParameter(i + 1, values[i]);
			}
		}
		//分页控制
		this.initPageSet(queryObject, pageController);

		return queryObject.getResultList();
	}

	/* (non-Javadoc)
	 * @see com.ulic.ucia.orm.jpa.JpaOperations#findByNamedParams(java.lang.String, java.util.Map)
	 */
	@SuppressWarnings("unchecked")
	public List findByNamedParams(final String queryString,
			final PageController pageController,
			final Map<String, ? extends Object> params)
			throws PersistenceException {

		Query queryObject = em.createQuery(queryString);
		if (params != null) {
			for (Map.Entry<String, ?> entry : params.entrySet()) {
				queryObject.setParameter(entry.getKey(), entry.getValue());
			}
		}
		//分页控制
		this.initPageSet(queryObject, pageController);

		return queryObject.getResultList();
	}

	/* (non-Javadoc)
	 * @see com.ulic.ucia.orm.jpa.JpaOperations#findByNamedQuery(java.lang.String)
	 */
	@SuppressWarnings("unchecked")
	public List findByNamedQuery(final String queryName,
			final PageController pageController) throws PersistenceException {
		return findByNamedQuery(queryName, pageController, (Object[]) null);
	}

	/* (non-Javadoc)
	 * @see com.ulic.ucia.orm.jpa.JpaOperations#findByNamedQuery(java.lang.String, java.lang.Object[])
	 */
	@SuppressWarnings("unchecked")
	public List findByNamedQuery(final String queryName,
			final PageController pageController, final Object... values)
			throws PersistenceException {
		Query queryObject = em.createNamedQuery(queryName);
		if (values != null) {
			for (int i = 0; i < values.length; i++) {
				queryObject.setParameter(i + 1, values[i]);
			}
		}
		//分页控制
		this.initPageSet(queryObject, pageController);

		return queryObject.getResultList();
	}

	/* (non-Javadoc)
	 * @see com.ulic.ucia.orm.jpa.JpaOperations#findByNamedQueryAndNamedParams(java.lang.String, java.util.Map)
	 */
	@SuppressWarnings("unchecked")
	public List findByNamedQueryAndNamedParams(final String queryName,
			final PageController pageController,
			Map<String, ? extends Object> params) throws PersistenceException {
		Query queryObject = em.createNamedQuery(queryName);
		if (params != null) {
			for (Map.Entry<String, ?> entry : params.entrySet()) {
				queryObject.setParameter(entry.getKey(), entry.getValue());
			}
		}
		//分页控制
		this.initPageSet(queryObject, pageController);

		return queryObject.getResultList();
	}

	/* (non-Javadoc)
	 * @see com.ulic.ucia.orm.jpa.JpaOperations#flush()
	 */
	public void flush() throws PersistenceException {

		em.flush();

	}

	/* (non-Javadoc)
	 * @see com.ulic.ucia.orm.jpa.JpaOperations#merge(java.lang.Object)
	 */
	public <T> T merge(T entity) throws PersistenceException {
		return em.merge(entity);
	}

	/* (non-Javadoc)
	 * @see com.ulic.ucia.orm.jpa.JpaOperations#persist(java.lang.Object)
	 */
	public void persist(Object entity) throws PersistenceException {
		em.persist(entity);

	}

	/* (non-Javadoc)
	 * @see com.ulic.ucia.orm.jpa.JpaOperations#refresh(java.lang.Object)
	 */
	public void refresh(Object entity) throws PersistenceException {
		em.refresh(entity);

	}

	/* (non-Javadoc)
	 * @see com.ulic.ucia.orm.jpa.JpaOperations#remove(java.lang.Object)
	 */
	public void remove(Object entity) throws PersistenceException {
		em.remove(entity);

	}

	/* (non-Javadoc)
	 * @see com.ulic.ucia.framework.orm.JpaOperations#executeUpdate(java.lang.String, java.lang.Object[])
	 */
	public int executeUpdate(String updateString, Object... values)
			throws PersistenceException {
		Query queryObject = em.createQuery(updateString);
		if (values != null) {
			for (int i = 0; i < values.length; i++) {
				queryObject.setParameter(i + 1, values[i]);
			}
		}
		return queryObject.executeUpdate();

	}

	/* (non-Javadoc)
	 * @see com.ulic.ucia.framework.orm.JpaOperations#executeUpdate(java.lang.String)
	 */
	public int executeUpdate(String updateString) throws PersistenceException {
		return executeUpdate(updateString, (Object[]) null);

	}

	/* (non-Javadoc)
	 * @see com.ulic.ucia.framework.orm.JpaOperations#executeUpdate(java.lang.String, java.util.Map)
	 */
	public int executeUpdate(String updateString,
			Map<String, ? extends Object> params) throws PersistenceException {
		Query queryObject = em.createQuery(updateString);
		if (params != null) {
			for (Map.Entry<String, ?> entry : params.entrySet()) {
				queryObject.setParameter(entry.getKey(), entry.getValue());
			}
		}
		return queryObject.executeUpdate();
	}

	/* (non-Javadoc)
	 * @see com.ulic.ucia.framework.orm.JpaOperations#executeNativeUpdate(java.lang.String, java.lang.Object[])
	 */
	public int executeNativeUpdate(String updateString, Object... values)
			throws PersistenceException {
		Query queryObject = em.createNativeQuery(updateString);
		if (values != null) {
			for (int i = 0; i < values.length; i++) {
				queryObject.setParameter(i + 1, values[i]);
			}
		}
		return queryObject.executeUpdate();

	}

	/* (non-Javadoc)
	 * @see com.ulic.ucia.framework.orm.JpaOperations#executeNativeUpdate(java.lang.String)
	 */
	public int executeNativeUpdate(String updateString) throws PersistenceException {
		return executeNativeUpdate(updateString, (Object[]) null);

	}

	/* (non-Javadoc)
	 * @see com.ulic.ucia.framework.orm.JpaOperations#executeNativeUpdate(java.lang.String, java.util.Map)
	 */
	public int executeNativeUpdate(String updateString,
			Map<String, ? extends Object> params) throws PersistenceException {
		Query queryObject = em.createNativeQuery(updateString);
		if (params != null) {
			for (Map.Entry<String, ?> entry : params.entrySet()) {
				queryObject.setParameter(entry.getKey(), entry.getValue());
			}
		}
		return queryObject.executeUpdate();
	}
	/* (non-Javadoc)
	 * @see com.ulic.ucia.orm.jpa.JpaOperations#findByNativeQuery(java.lang.String)
	 */
	@SuppressWarnings("unchecked")
	public List findByNativeQuery(String sqlString,
			final PageController pageController) throws PersistenceException {
		return findByNativeQuery(sqlString,pageController,(Object[])null);
	}
	
	/* (non-Javadoc)
	 * @see com.ulic.ucia.orm.jpa.JpaOperations#findByNativeQuery(java.lang.String)
	 */
	@SuppressWarnings("unchecked")
	public List findByNativeQuery(String sqlString,
			final PageController pageController, Object... values) throws PersistenceException {
        return findByNativeQuery(sqlString,null,pageController,values);
	}

	/* (non-Javadoc)
	 * @see com.ulic.ucia.orm.jpa.JpaOperations#findByNativeQuery(java.lang.String, java.lang.Class,PageController,Object)
	 */

	@SuppressWarnings("unchecked")
	public List findByNativeQuery(String sqlString, Class entityClass,
			final PageController pageController, Object... values) throws PersistenceException {
		Query queryObject;
		
		if (entityClass!=null) {
			queryObject = em.createNativeQuery(sqlString, entityClass);
		} else {
			queryObject = em.createNativeQuery(sqlString);
		}
		
		if (values != null) {
			for (int i = 0; i < values.length; i++) {
				queryObject.setParameter(i + 1, values[i]);
			}
		}
		//分页控制
		this.initPageSet(queryObject, pageController);
		return queryObject.getResultList();
	}
	

	/* (non-Javadoc)
	 * @see com.ulic.ucia.orm.jpa.JpaOperations#findByNativeQuery(java.lang.String, java.lang.Class)
	 */

	@SuppressWarnings("unchecked")
	public List findByNativeQuery(String sqlString, Class entityClass,
			final PageController pageController) throws PersistenceException {
		return findByNativeQuery(sqlString,entityClass,pageController,(Object[])null);
	}

	/* (non-Javadoc)
	 * @see com.ulic.ucia.orm.jpa.JpaOperations#lock(java.lang.Object, com.ulic.ucia.orm.jpa.support.LockMode)
	 */
	public void lock(Object obj, JpaLockMode lockMode)
			throws PersistenceException {

		em.lock(obj, lockMode.getLockModeType());

	}

	/* (non-Javadoc)
	 * @see com.ulic.ucia.orm.jpa.JpaOperations#clear()
	 */
	public void clear() throws PersistenceException {
		em.clear();

	}

	/* (non-Javadoc)
	 * @see com.ulic.ucia.orm.jpa.JpaOperations#findByNativeQuery(java.lang.String, java.lang.String)
	 */
	@SuppressWarnings("unchecked")
	public List findByNativeQuery(String sqlString, String sqlMapingName,
			final PageController pageController) throws PersistenceException {
		Query queryObject = em.createNativeQuery(sqlString, sqlMapingName);
		//分页控制
		this.initPageSet(queryObject, pageController);
		return queryObject.getResultList();
	}

	/* (non-Javadoc)
	 * @see com.ulic.ucia.orm.jpa.JpaOperations#callProcedure(java.lang.String, java.lang.Object[])
	 */
	public Object callProcedure(String callString, Object... values)
			throws PersistenceException {
		Query queryObject = em.createNativeQuery("select "+callString+" from dual");
		if (values != null) {
			for (int i = 0; i < values.length; i++) {
				queryObject.setParameter(i + 1, values[i]);
			}
		}
		return queryObject.getSingleResult();
	}

	/* (non-Javadoc)
	 * @see com.ulic.ucia.orm.jpa.JpaOperations#callProcedure(java.lang.String)
	 */
	public Object callProcedure(String callString) throws PersistenceException {
		return this.callProcedure(callString, (Object[]) null);
	}

	/* (non-Javadoc)
	 * @see com.ulic.ucia.orm.jpa.JpaOperations#excuteProcedure(java.lang.String, java.lang.Object[])
	 */
	public void excuteProcedure(String callString, Object... values)
			throws PersistenceException {
		Query queryObject = em.createNativeQuery("{call "+callString + "}");
		if (values != null) {
			for (int i = 0; i < values.length; i++) {
				queryObject.setParameter(i + 1, values[i]);
			}
		}
		queryObject.executeUpdate();

	}

	/* (non-Javadoc)
	 * @see com.ulic.ucia.orm.jpa.JpaOperations#excuteProcedure(java.lang.String)
	 */
	public void excuteProcedure(String callString) throws PersistenceException {
		this.excuteProcedure(callString, (Object[]) null);

	}

	/**设置分页查询的配置 
	 * @param query  JPA Query对象
	 * @param pageController 分页控制器
	 */
	private void initPageSet(Query query, final PageController pageController) {
		//如果分页控制器不为空,则进行分页设置
		if (pageController != null) {
			query.setFirstResult((pageController.getPageNo() - 1)
					* pageController.getPageSize());
			query.setMaxResults(pageController.getPageSize());
		}

	}

}
